home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / POVRAY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-21  |  50.8 KB  |  2,334 lines

  1. /****************************************************************************
  2. *                povray.c
  3. *
  4. *  This module contains the entry routine for the raytracer and the code to
  5. *  parse the parameters on the command line.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24. #include <ctype.h>
  25. #include <time.h>     /* BP */
  26. #include "frame.h"
  27. #include "povproto.h"
  28. #include "bezier.h"
  29. #include "blob.h"
  30. #include "bbox.h"
  31. #include "cones.h"
  32. #include "csg.h"
  33. #include "discs.h"
  34. #include "express.h"
  35. #include "fractal.h"
  36. #include "hfield.h"
  37. #include "lathe.h"
  38. #include "lighting.h"
  39. #include "mem.h"
  40. #include "mesh.h"
  41. #include "polysolv.h"
  42. #include "objects.h"
  43. #include "octree.h"
  44. #include "parse.h"
  45. #include "pigment.h"
  46. #include "point.h"
  47. #include "poly.h"
  48. #include "polygon.h"
  49. #include "povray.h"
  50. #include "optin.h"
  51. #include "optout.h"
  52. #include "quadrics.h"
  53. #include "pgm.h"
  54. #include "png_pov.h"
  55. #include "ppm.h"
  56. #include "prism.h"
  57. #include "radiosit.h"
  58. #include "render.h"
  59. #include "sor.h"
  60. #include "spheres.h"
  61. #include "super.h"
  62. #include "targa.h"
  63. #include "texture.h"
  64. #include "tokenize.h"
  65. #include "torus.h"
  66. #include "triangle.h"
  67. #include "truetype.h"
  68. #include "userio.h"     /*Error,Warning,Init_Text_Streams*/
  69. #include "lbuffer.h"
  70. #include "vbuffer.h"
  71.  
  72.  
  73. /*****************************************************************************
  74. * Local preprocessor defines
  75. ******************************************************************************/
  76.  
  77. /* Flags for the variable store. */
  78.  
  79. #define STORE   1
  80. #define RESTORE 2
  81.  
  82.  
  83.  
  84. /*****************************************************************************
  85. * Local typedefs
  86. ******************************************************************************/
  87.  
  88.  
  89.  
  90. /*****************************************************************************
  91. * Local variables
  92. ******************************************************************************/
  93.  
  94. /* The frame. */
  95.  
  96. FRAME Frame;
  97.  
  98. /* Options and display stuff. */
  99.  
  100. char Color_Bits;
  101.  
  102. int Display_Started;
  103. int Blanker_Started;
  104.  
  105. int Abort_Test_Every;
  106.  
  107. /* Current stage of the program. */
  108.  
  109. int Stage;
  110.  
  111. /* Flag if -h option will show help screens. */
  112.  
  113. int Help_Available;
  114.  
  115. /* File and parsing stuff. */
  116.  
  117. Opts opts;
  118. COUNTER stats[MaxStat];
  119. COUNTER totalstats[MaxStat];
  120.  
  121. int Num_Echo_Lines;      /* May make user setable later - CEY*/
  122. int Echo_Line_Length;    /* May make user setable later - CEY*/
  123.  
  124. int Number_Of_Files;
  125.  
  126. FILE *stat_file;
  127. FILE_HANDLE *Output_File_Handle;
  128.  
  129. char Actual_Output_Name[FILE_NAME_LENGTH];
  130.  
  131. /* Timing stuff .*/
  132.  
  133. time_t tstart, tstop;
  134. DBL tparse, trender, tparse_total, trender_total;
  135.  
  136. /* Variable used by vector macros. */
  137.  
  138. DBL VTemp;
  139.  
  140. volatile int Stop_Flag;
  141.  
  142. /* Flag if close_all() was already called. */
  143. static int closed_flag;
  144.  
  145. int pre_init_flag=0;
  146.  
  147. char *Option_String_Ptr;      
  148.  
  149. /*****************************************************************************
  150. * Static functions
  151. ******************************************************************************/
  152.  
  153. static void init_vars PARAMS((void));
  154. static void destroy_libraries PARAMS((void));
  155. static void fix_up_rendering_window PARAMS((void));
  156. static void fix_up_animation_values PARAMS((void));
  157. static void fix_up_scene_name PARAMS((void));
  158. static void set_output_file_handle PARAMS((void));
  159. static void setup_output_file_name PARAMS((void));
  160. static void open_output_file PARAMS((void));
  161. static void FrameRender PARAMS((void));
  162. static void init_statistics PARAMS((COUNTER *));
  163. static void sum_statistics PARAMS((COUNTER *, COUNTER *));
  164. static void variable_store PARAMS((int Flag));
  165. static int Has_Extension PARAMS((char *name));
  166. static unsigned closest_power_of_2 PARAMS((unsigned theNumber));
  167. static void init_shellouts PARAMS((void));
  168. static void destroy_shellouts PARAMS((void));
  169.  
  170.  
  171. /*****************************************************************************
  172. *
  173. * FUNCTION
  174. *
  175. *   main
  176. *
  177. * INPUT
  178. *   
  179. * OUTPUT
  180. *   
  181. * RETURNS
  182. *
  183. * AUTHOR
  184. *
  185. *   POV-Ray Team
  186. *   
  187. * DESCRIPTION
  188. *
  189. *   -
  190. *
  191. * CHANGES
  192. *
  193. *   -
  194. *
  195. ******************************************************************************/
  196.  
  197.  
  198. #ifdef NOCMDLINE    /* a main() by any other name... */
  199. #ifdef ALTMAIN
  200.   MAIN_RETURN_TYPE alt_main()
  201. #else
  202.   MAIN_RETURN_TYPE main()
  203. #endif
  204. #else
  205. #ifdef ALTMAIN
  206.   MAIN_RETURN_TYPE alt_main(argc, argv)
  207. #else
  208.   MAIN_RETURN_TYPE main(argc, argv)
  209. #endif
  210. int argc;
  211. char **argv;
  212. #endif            /* ...would be a lot less hassle!! :-) AAC */
  213. {
  214.   register int i;
  215.   int Diff_Frame;
  216.   DBL Diff_Clock;
  217.   SHELLRET Pre_Scene_Result, Frame_Result;
  218.  
  219.   /* Attention all ALTMAIN people! See comments attached to this function*/
  220.   pre_init_povray();
  221.  
  222.   /* Startup povray. */
  223.   Stage = STAGE_STARTUP;
  224.   STARTUP_POVRAY
  225.  
  226. #ifndef NOCMDLINE
  227.   /* Print help screens. */
  228.  
  229.   if (argc == 1)
  230.   {
  231.     Print_Help_Screens();
  232.   }
  233. #endif
  234.  
  235.   /* Initialize variables. */
  236.   init_vars();
  237.  
  238.   Stage = STAGE_ENVIRONMENT;
  239.  
  240.   READ_ENV_VAR
  241.  
  242.   Stage = STAGE_INI_FILE;
  243.  
  244.   /* Read parameters from POVRAY.INI */
  245.   PROCESS_POVRAY_INI
  246.  
  247. #ifndef NOCMDLINE
  248.   /* Parse the command line parameters */
  249.  
  250.   Stage = STAGE_COMMAND_LINE;
  251.  
  252.   Help_Available = (argc == 2);
  253.  
  254.   for (i = 1 ; i < argc ; i++ )
  255.   {
  256.     parse_option_line(argv[i]);
  257.   }
  258. #endif
  259.  
  260.   /* Print banner and credit info. */
  261.   Stage = STAGE_BANNER;
  262.   if (opts.Options & VERBOSE)
  263.   {
  264.   PRINT_CREDITS
  265.   PRINT_OTHER_CREDITS
  266.   }
  267.  
  268.   /* Strip path and extension off input name to create scene name */
  269.   fix_up_scene_name ();
  270.   
  271.   /* Redirect text streams [SCD 2/95] */
  272.   Open_Text_Streams();
  273.  
  274.   /* Write .INI file [SCD 2/95] */
  275.   Write_INI_File();
  276.   
  277.   ALT_WRITE_INI_FILE
  278.  
  279.   /* Make sure clock is okay, validate animation parameters */
  280.   fix_up_animation_values();
  281.  
  282.   /* Fix-up rendering window values if necessary. */
  283.   fix_up_rendering_window();
  284.   
  285.   /* Set output file handle for options screen. */
  286.   set_output_file_handle();
  287.  
  288.   /* Print options used. */
  289.   Print_Options();
  290.   
  291.   /* BEGIN SECTION */
  292.   /* VARIOUS INITIALIZATION THAT ONLY NEEDS TO BE DONE 1/EXECUTION */
  293.  
  294.   /* Set up noise-tables. */
  295.   Initialize_Noise();
  296.   
  297.   Diff_Clock = opts.FrameSeq.FinalClock - opts.FrameSeq.InitialClock;
  298.  
  299.   if (opts.Options & CYCLIC_ANIMATION)
  300.   {
  301.     Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1;
  302.   }
  303.   else
  304.   {
  305.     Diff_Frame = opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame;
  306.   }
  307.   
  308.   /* END SECTION */
  309.  
  310.   /* Execute the first shell-out command */
  311.   Pre_Scene_Result=POV_SHELLOUT(PRE_SCENE_SHL);
  312.  
  313.   /* Loop over each frame */
  314.   
  315.   if (Pre_Scene_Result != ALL_SKIP_RET)
  316.   {
  317.      if (Pre_Scene_Result != SKIP_ONCE_RET)
  318.      {
  319.        for (opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame,
  320.             opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
  321.  
  322.             opts.FrameSeq.FrameNumber <= opts.FrameSeq.FinalFrame;
  323.  
  324.             opts.FrameSeq.FrameNumber++,
  325.             opts.FrameSeq.Clock_Value += ((Diff_Frame==0)?1:Diff_Clock/Diff_Frame))
  326.        {
  327.          setup_output_file_name();
  328.  
  329.          /* Execute a shell-out command before tracing */
  330.  
  331.          Frame_Result=POV_SHELLOUT(PRE_FRAME_SHL);
  332.            
  333.          if (Frame_Result == ALL_SKIP_RET)
  334.          {
  335.            break;
  336.          }
  337.  
  338.          if (Frame_Result != SKIP_ONCE_RET)
  339.          {
  340.            FrameRender();
  341.  
  342.            /* Execute a shell-out command after tracing */
  343.  
  344.            Frame_Result = POV_SHELLOUT(POST_FRAME_SHL);
  345.            
  346.            if ((Frame_Result==SKIP_ONCE_RET) || (Frame_Result==ALL_SKIP_RET))
  347.            {
  348.              break;
  349.            }
  350.          }
  351.        }
  352.  
  353.        /* Print total stats ... */
  354.  
  355.        if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  356.        {
  357.          Statistics("\nTotal Statistics");
  358.     
  359.          opts.FrameSeq.FrameNumber--;
  360.  
  361.          PRINT_STATS(totalstats);
  362.     
  363.          opts.FrameSeq.FrameNumber++;
  364.        }
  365.      }
  366.  
  367.      /* Execute the final shell-out command */
  368.  
  369.      POV_SHELLOUT(POST_SCENE_SHL);
  370.   }
  371.  
  372.   /* And finish. */
  373.  
  374.   Terminate_POV(0);
  375.  
  376.   MAIN_RETURN_STATEMENT
  377. } /* main */
  378.  
  379.  
  380. /*****************************************************************************
  381. *
  382. * FUNCTION
  383. *
  384. *   FrameRender
  385. *
  386. * INPUT
  387. *   
  388. * OUTPUT
  389. *   
  390. * RETURNS
  391. *   
  392. * AUTHOR
  393. *
  394. *   POV-Ray Team
  395. *   
  396. * DESCRIPTION
  397. *
  398. *   Do all that is necessary for rendering a single frame, including parsing
  399. *
  400. * CHANGES
  401. *
  402. *   Feb 1996: Make sure we are displaying when doing a mosaic preview [AED]
  403. *
  404. ******************************************************************************/
  405.  
  406. static void FrameRender()
  407. {
  408.   unsigned long hours, minutes;
  409.   DBL seconds, t_total;
  410.  
  411.   /* Store start time for parse. */
  412.   START_TIME
  413.  
  414.   /* Parse the scene file. */
  415.   Status_Info("\n\nParsing...");
  416.   
  417.   opts.Do_Stats=FALSE;
  418.  
  419.   Init_Random_Generators();
  420.  
  421.   Parse();
  422.  
  423.   Destroy_Random_Generators();
  424.  
  425.   opts.Do_Stats=TRUE;
  426.  
  427.   /* Switch off standard anti-aliasing. */
  428.  
  429.   if ((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
  430.   {
  431.     opts.Options &= ~ANTIALIAS;
  432.  
  433.     Warning(0.0, "Focal blur is used. Standard antialiasing is switched off.\n");
  434.   }
  435.  
  436.   /* Create the bounding box hierarchy. */
  437.  
  438.   Stage = STAGE_SLAB_BUILDING;
  439.  
  440.   if (opts.Use_Slabs)
  441.   {
  442.     Status_Info("\nCreating bounding slabs.");
  443.   }
  444.  
  445.   /* Init module specific stuff. */
  446.   Initialize_Atmosphere_Code();
  447.   Initialize_BBox_Code();
  448.   Initialize_Lighting_Code();
  449.   Initialize_Mesh_Code();
  450.   Initialize_VLBuffer_Code();
  451.   Initialize_Radiosity_Code();
  452.  
  453.   /* Always call this to print number of objects. */
  454.   Build_Bounding_Slabs(&Root_Object);
  455.  
  456.   /* Create the vista buffer. */
  457.   Build_Vista_Buffer();
  458.  
  459.   /* Create the light buffers. */
  460.   Build_Light_Buffers();
  461.  
  462.   /* Create blob queue. */
  463.   Init_Blob_Queue();
  464.  
  465.   /* Save variable values. */
  466.   variable_store(STORE);
  467.  
  468.   /* Open output file and if we are continuing an interrupted trace,
  469.    * read in the previous file settings and any data there.  This has to
  470.    * be done before any image-size related allocations, since the settings
  471.    * in a resumed file take precedence over that specified by the user. [AED]
  472.    */
  473.   open_output_file();
  474.  
  475.   /* Start the display. */
  476.  
  477.   if (opts.Options & DISPLAY)
  478.   {
  479.     Status_Info ("\nDisplaying...");
  480.     POV_DISPLAY_INIT(Frame.Screen_Width, Frame.Screen_Height, 0, opts.DisplayFormat);
  481.     Display_Started = TRUE;
  482.     Draw_Vista_Buffer();
  483.   }
  484.   else
  485.   {
  486.   if (!(opts.Options & VERBOSE))
  487.   {
  488.     POV_DISPLAY_INIT(Frame.Screen_Width, Frame.Screen_Height, 1, opts.DisplayFormat);
  489.     Blanker_Started = TRUE;
  490.   }
  491.   }
  492.  
  493.   /* Get things ready for ray tracing (misc init, mem alloc) */
  494.   Initialize_Renderer();
  495.  
  496.   /* This had to be taken out of open_output_file() because we don't have
  497.    * the final image size until the output file has been opened, so we can't
  498.    * initialize the display until we know this, which in turn means we can't
  499.    * read the rendered part before the display is initialized. [AED]
  500.    */
  501.   if ((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
  502.   {
  503.     Read_Rendered_Part(Actual_Output_Name);
  504.  
  505.     if (opts.Last_Line > Frame.Screen_Height)
  506.       opts.Last_Line = Frame.Screen_Height;
  507.  
  508.     if (opts.Last_Column > Frame.Screen_Width)
  509.       opts.Last_Column = Frame.Screen_Width;
  510.  
  511.   }
  512.  
  513.   /* Get parsing time. */
  514.   STOP_TIME
  515.   tparse = TIME_ELAPSED
  516.   tparse /= 200.0;
  517.  
  518.   /* Get total parsing time. */
  519.   tparse_total += tparse;
  520.  
  521.   /* Store start time for trace. */
  522.   START_TIME
  523.  
  524.   if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  525.   {
  526.     t_total=tparse_total+trender_total;
  527.     SPLIT_TIME(t_total,&hours,&minutes,&seconds);
  528.     Render_Info("\n %02ld:%02ld:%02.0f so far, ",hours,minutes,seconds);
  529.     Render_Info("Rendering frame %d, going to %d.",
  530.         opts.FrameSeq.FrameNumber, opts.FrameSeq.FinalFrame);
  531.   }
  532.   /* Start tracing. */
  533.   Stage = STAGE_RENDERING;
  534.  
  535.   POV_PRE_RENDER
  536.  
  537.   Status_Info ("\nRendering...\r");
  538.  
  539.   /* Macro for setting up any special FP options */
  540.   CONFIG_MATH
  541.  
  542.   /* Ok, go for it - trace the picture. */
  543.  
  544.   /* If radiosity preview has been done, we are continuing a trace, so it
  545.    * is important NOT to do the preview, even if the user requests it, as it
  546.    * will cause discontinuities in radiosity shading by (probably) calculating
  547.    * a few more radiosity values.
  548.    */
  549.   if ( !opts.Radiosity_Preview_Done )
  550.   {
  551.     if ( opts.Options & RADIOSITY )
  552.     {
  553.       /* Note that radiosity REQUIRES a mosaic preview prior to main scan */
  554.  
  555.       Start_Tracing_Mosaic_Smooth(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
  556.     }
  557.     else
  558.     {
  559.       if (opts.Options & PREVIEW && opts.Options & DISPLAY)
  560.       {
  561.         Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);
  562.       }
  563.     }
  564.   }
  565.  
  566.   switch (opts.Tracing_Method)
  567.   {
  568.     case 2 :
  569.  
  570.       Start_Adaptive_Tracing();
  571.  
  572.       break;
  573.  
  574.     case 1 :
  575.     default:
  576.  
  577.       Start_Non_Adaptive_Tracing();
  578.   }
  579.  
  580.   /* We're done. */
  581.  
  582.   /* Record time so well spent before file close so it can be in comments  */
  583.   STOP_TIME
  584.   trender = TIME_ELAPSED
  585.   trender /= 200.0;
  586.  
  587.   /* Close out our file */
  588.   if (Output_File_Handle)
  589.   {
  590.      Close_File(Output_File_Handle);
  591.   }
  592.  
  593.   Stage = STAGE_SHUTDOWN;
  594.  
  595.   POV_PRE_SHUTDOWN
  596.  
  597.   /* DESTROY lots of stuff */
  598.   Deinitialize_Atmosphere_Code();
  599.   Deinitialize_BBox_Code();
  600.   Deinitialize_Lighting_Code();
  601.   Deinitialize_Mesh_Code();
  602.   Deinitialize_VLBuffer_Code();
  603.   Deinitialize_Radiosity_Code();
  604.   Destroy_Blob_Queue();
  605.   Destroy_Light_Buffers();
  606.   Destroy_Vista_Buffer();
  607.   Destroy_Bounding_Slabs();
  608.   Destroy_Frame();
  609.   Terminate_Renderer();
  610.   FreeFontInfo();
  611.   Free_Iteration_Stack();
  612.  
  613.   POV_POST_SHUTDOWN
  614.  
  615.   /* Get total render time. */
  616.   trender_total += trender;
  617.  
  618.   POV_DISPLAY_FINISHED
  619.  
  620.   if ((opts.Options & DISPLAY) && Display_Started)
  621.   {
  622.     POV_DISPLAY_CLOSE
  623.     Display_Started = FALSE;
  624.   }
  625.   else
  626.   {
  627.   if ((!(opts.Options & VERBOSE)) && Blanker_Started)
  628.   {
  629.     POV_DISPLAY_CLOSE
  630.     Blanker_Started = FALSE;
  631.   }
  632.   }
  633.  
  634.   if (opts.histogram_on)
  635.     write_histogram (opts.Histogram_File_Name) ;
  636.  
  637.   Status_Info("\nDone Tracing");
  638.  
  639.   /* Print stats ... */
  640.   PRINT_STATS(stats);
  641.  
  642.   if(opts.FrameSeq.FrameType==FT_MULTIPLE_FRAME)
  643.   {
  644.     /* Add them up */
  645.     sum_statistics(totalstats, stats);
  646.  
  647.     /* ... and then clear them for the next frame */
  648.     init_statistics(stats);
  649.   }
  650.  
  651.   /* Restore variable values. */
  652.   variable_store(RESTORE);
  653.  
  654. }
  655.  
  656. /*****************************************************************************
  657. *
  658. * FUNCTION
  659. *
  660. *   fix_up_rendering_window
  661. *
  662. * INPUT
  663. *   
  664. * OUTPUT
  665. *   
  666. * RETURNS
  667. *   
  668. * AUTHOR
  669. *
  670. *   POV-Ray Team
  671. *   
  672. * DESCRIPTION
  673. *
  674. *   Fix wrong window and mosaic preview values.
  675. *
  676. * CHANGES
  677. *
  678. *   -
  679. *
  680. ******************************************************************************/
  681.  
  682. static void fix_up_rendering_window()
  683. {
  684.   int temp;
  685.   
  686.   if (opts.First_Column_Percent > 0.0)
  687.     opts.First_Column = (int) (Frame.Screen_Width * opts.First_Column_Percent);
  688.  
  689.   if (opts.First_Line_Percent > 0.0)
  690.     opts.First_Line = (int) (Frame.Screen_Height * opts.First_Line_Percent);
  691.  
  692.   /* The decrements are a fudge factor that used to be in OPTIN.C
  693.    * but it messed up Write_INI_File so its moved here.
  694.    */
  695.  
  696.   if (opts.First_Column <= 0)
  697.     opts.First_Column = 0;
  698.   else
  699.     opts.First_Column--;
  700.  
  701.   if (opts.First_Line <= 0)
  702.     opts.First_Line = 0;
  703.   else
  704.     opts.First_Line--;
  705.   
  706.   if ((opts.Last_Column == -1) && (opts.Last_Column_Percent <= 1.0))
  707.     opts.Last_Column = (int) (Frame.Screen_Width * opts.Last_Column_Percent);
  708.  
  709.   if ((opts.Last_Line == -1) && (opts.Last_Line_Percent <= 1.0))
  710.     opts.Last_Line = (int) (Frame.Screen_Height * opts.Last_Line_Percent);
  711.  
  712.   if (opts.Last_Line == -1)
  713.     opts.Last_Line = Frame.Screen_Height;
  714.  
  715.   if (opts.Last_Column == -1)
  716.     opts.Last_Column = Frame.Screen_Width;
  717.  
  718.   if (opts.Last_Column < 0 || opts.Last_Column > Frame.Screen_Width)
  719.     opts.Last_Column = Frame.Screen_Width;
  720.  
  721.   if (opts.Last_Line > Frame.Screen_Height)
  722.     opts.Last_Line = Frame.Screen_Height;
  723.  
  724.   /* Fix up Mosaic Preview values */
  725.   opts.PreviewGridSize_Start=max(1,opts.PreviewGridSize_Start);
  726.   opts.PreviewGridSize_End=max(1,opts.PreviewGridSize_End);
  727.  
  728.   if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_Start))!=opts.PreviewGridSize_Start)
  729.   {
  730.      Warning(0.0,"Preview_Start_Size must be a power of 2. Changing to %d.\n",temp);
  731.      opts.PreviewGridSize_Start=temp;
  732.   }
  733.  
  734.   if ((temp=closest_power_of_2((unsigned)opts.PreviewGridSize_End))!=opts.PreviewGridSize_End)
  735.   {
  736.      Warning(0.0,"Preview_End_Size must be a power of 2. Changing to %d.\n",temp);
  737.      opts.PreviewGridSize_End=temp;
  738.   }
  739.  
  740.   /* End must be less than or equal to start */
  741.   if (opts.PreviewGridSize_End > opts.PreviewGridSize_Start)
  742.     opts.PreviewGridSize_End = opts.PreviewGridSize_Start;
  743.     
  744.   if (opts.PreviewGridSize_Start > 1)
  745.   {
  746.      opts.PreviewGridSize_End=max(opts.PreviewGridSize_End,2);
  747.      opts.Options |= PREVIEW;
  748.   }
  749.   else
  750.   {
  751.      opts.Options &= ~PREVIEW;
  752.   }
  753.  
  754.   /* Set histogram size here so it is available for Print_Options, and
  755.    * make sure that it has an integer number of pixels/bucket. */
  756.   if (opts.histogram_on)
  757.   {
  758.     if (opts.histogram_x == 0 || opts.histogram_x > Frame.Screen_Width)
  759.       opts.histogram_x = Frame.Screen_Width;
  760.     else if (opts.histogram_x < Frame.Screen_Width)
  761.       opts.histogram_x = Frame.Screen_Width / ((Frame.Screen_Width +
  762.                          opts.histogram_x - 1) / opts.histogram_x);
  763.  
  764.     if (opts.histogram_y == 0 || opts.histogram_y > Frame.Screen_Height)
  765.       opts.histogram_y = Frame.Screen_Height;
  766.     else if (opts.histogram_y < Frame.Screen_Height)
  767.       opts.histogram_y = Frame.Screen_Height / ((Frame.Screen_Height +
  768.                          opts.histogram_y - 1) /opts.histogram_y);
  769.   }
  770. }
  771.  
  772. /*****************************************************************************
  773. *
  774. * FUNCTION
  775. *
  776. *   fix_up_animation_values
  777. *
  778. * INPUT
  779. *   
  780. * OUTPUT
  781. *   
  782. * RETURNS
  783. *   
  784. * AUTHOR
  785. *
  786. *   POV-Ray Team
  787. *   
  788. * DESCRIPTION
  789. *
  790. *   Validate animation parameters, compute subset values
  791. *
  792. * CHANGES
  793. *
  794. *   -
  795. *
  796. ******************************************************************************/
  797. static void fix_up_animation_values()
  798. {
  799.   float ClockDiff;
  800.   int FrameDiff;
  801.   int FrameIncr;
  802.   float ClockPerFrameIncr;
  803.   int NumFrames;
  804.  
  805.   if (opts.FrameSeq.FinalFrame != -1)
  806.   {
  807.     opts.FrameSeq.FrameType = FT_MULTIPLE_FRAME;
  808.  
  809.     if (opts.FrameSeq.Clock_Value != 0.0)
  810.     {
  811.        Warning(0.0,"Attempted to set single clock value in multi frame\nanimation. Clock value overridden.\n");
  812.     }
  813.   }
  814.   else
  815.   {
  816.     if (opts.FrameSeq.Clock_Value != 0.0)
  817.     {
  818.        opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
  819.     }
  820.   }
  821.  
  822.   if (opts.FrameSeq.FrameType == FT_SINGLE_FRAME)
  823.   {
  824.     /*
  825.      * These are dummy values that will work for single_frame,
  826.      * even in an animation loop.
  827.      */
  828.  
  829.     opts.FrameSeq.InitialFrame = 0;
  830.     opts.FrameSeq.FinalFrame   = 0;
  831.     opts.FrameSeq.InitialClock = opts.FrameSeq.Clock_Value;
  832.     opts.FrameSeq.FinalClock   = 0.0;
  833.   }
  834.   else
  835.   {
  836.     /* FrameType==FT_MULTIPLE_FRAME */
  837.  
  838.     if(opts.FrameSeq.InitialFrame == -1)
  839.     {
  840.       opts.FrameSeq.InitialFrame = 1;
  841.     }
  842.  
  843.     if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
  844.     {
  845.       Error("Final frame %d is less than Start Frame %d.\n",
  846.             opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
  847.     }
  848.  
  849.     ClockDiff = opts.FrameSeq.FinalClock-opts.FrameSeq.InitialClock;
  850.  
  851.     if (opts.Options & CYCLIC_ANIMATION)
  852.     {
  853.       FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame+1;
  854.     }
  855.     else
  856.     {
  857.       FrameDiff = opts.FrameSeq.FinalFrame-opts.FrameSeq.InitialFrame;
  858.     }
  859.  
  860.     ClockPerFrameIncr = (FrameDiff == 0) ? 0 : (ClockDiff/FrameDiff);
  861.  
  862.     /* Calculate width, which is an integer log10 */
  863.  
  864.     NumFrames = opts.FrameSeq.FinalFrame;
  865.  
  866.     opts.FrameSeq.FrameNumWidth = 1;
  867.  
  868.     while (NumFrames >= 10)
  869.     {
  870.       opts.FrameSeq.FrameNumWidth++;
  871.  
  872.       NumFrames = NumFrames / 10;
  873.     }
  874.  
  875.     if (opts.FrameSeq.FrameNumWidth > POV_NAME_MAX-1)
  876.     {
  877.       Error("Can't render %d frames requiring %d chars with %d width filename.\n",
  878.           opts.FrameSeq.FinalFrame - opts.FrameSeq.InitialFrame + 1,
  879.           opts.FrameSeq.FrameNumWidth, POV_NAME_MAX);
  880.     }
  881.  
  882.     /* STARTING FRAME SUBSET */
  883.  
  884.     if (opts.FrameSeq.SubsetStartPercent != DBL_VALUE_UNSET)
  885.     {
  886.       FrameIncr = FrameDiff * opts.FrameSeq.SubsetStartPercent + 0.5; /* w/rounding */
  887.  
  888.       opts.FrameSeq.SubsetStartFrame = opts.FrameSeq.InitialFrame + FrameIncr;
  889.     }
  890.  
  891.     if (opts.FrameSeq.SubsetStartFrame != INT_VALUE_UNSET)
  892.     {
  893.       NumFrames = opts.FrameSeq.SubsetStartFrame - opts.FrameSeq.InitialFrame;
  894.  
  895.       opts.FrameSeq.InitialFrame = opts.FrameSeq.SubsetStartFrame;
  896.       opts.FrameSeq.InitialClock = opts.FrameSeq.InitialClock + NumFrames * ClockPerFrameIncr;
  897.     }
  898.  
  899.     /* ENDING FRAME SUBSET */
  900.  
  901.     if (opts.FrameSeq.SubsetEndPercent != DBL_VALUE_UNSET)
  902.     {
  903.       /*
  904.        * By this time, we have possibly lost InitialFrame, so we calculate
  905.        * it via FinalFrame-FrameDiff
  906.        */
  907.  
  908.       FrameIncr = FrameDiff * opts.FrameSeq.SubsetEndPercent + 0.5; /* w/rounding */
  909.  
  910.       opts.FrameSeq.SubsetEndFrame = (opts.FrameSeq.FinalFrame - FrameDiff) + FrameIncr;
  911.     }
  912.  
  913.     if (opts.FrameSeq.SubsetEndFrame != INT_VALUE_UNSET)
  914.     {
  915.       NumFrames = opts.FrameSeq.FinalFrame - opts.FrameSeq.SubsetEndFrame;
  916.  
  917.       opts.FrameSeq.FinalFrame = opts.FrameSeq.SubsetEndFrame;
  918.       opts.FrameSeq.FinalClock = opts.FrameSeq.FinalClock - NumFrames * ClockPerFrameIncr;
  919.     }
  920.  
  921.     /*
  922.      * Now that we have everything calculated, we check FinalFrame
  923.      * and InitialFrame one more time, in case the subsets messed them up
  924.      */
  925.  
  926.     if (opts.FrameSeq.FinalFrame < opts.FrameSeq.InitialFrame)
  927.     {
  928.       Error("Final frame %d is less than Start Frame %d\ndue to bad subset specification.\n",
  929.             opts.FrameSeq.FinalFrame, opts.FrameSeq.InitialFrame);
  930.     }
  931.   }
  932.  
  933.   /* Needed for pre-render shellout fixup */
  934.  
  935.   opts.FrameSeq.FrameNumber = opts.FrameSeq.InitialFrame;
  936.   opts.FrameSeq.Clock_Value = opts.FrameSeq.InitialClock;
  937. }
  938.  
  939. /*****************************************************************************
  940. *
  941. * FUNCTION
  942. *
  943. *   fix_up_scene_name
  944. *
  945. * INPUT
  946. *   
  947. * OUTPUT
  948. *   
  949. * RETURNS
  950. *   
  951. * AUTHOR
  952. *
  953. *   POV-Ray Team
  954. *   
  955. * DESCRIPTION
  956. *
  957. *   Strip path and extention of input file to create scene name
  958. *
  959. * CHANGES
  960. *
  961. *   Feb 1996: changed scene name for standard input to "stdin" from "-"
  962. *
  963. ******************************************************************************/
  964.  
  965. static void fix_up_scene_name()
  966. {
  967.   int i, l;
  968.   char temp[FILE_NAME_LENGTH];
  969.   
  970.   if ((l=strlen(opts.Input_File_Name)-1)<1)
  971.   {
  972.      if (opts.Input_File_Name[0] == '-')
  973.        strcpy(opts.Scene_Name,"stdin");
  974.      else
  975.        strcpy(opts.Scene_Name,opts.Input_File_Name);
  976.      return;
  977.   }
  978.  
  979.   strcpy(temp,opts.Input_File_Name);
  980.   for (i=l;i>0;i--)
  981.   {
  982.      if (temp[i]==FILENAME_SEPARATOR)
  983.      {
  984.         break;
  985.      }
  986.      if (temp[i]=='.')
  987.      {
  988.         temp[i]=0;
  989.         break;
  990.      }
  991.   }
  992.  
  993.   i=strlen(temp)-1;
  994.   
  995.   while ((i>0) && (temp[i]!=FILENAME_SEPARATOR))
  996.     i--;
  997.   if (temp[i]==FILENAME_SEPARATOR)
  998.     i++;
  999.   strcpy(opts.Scene_Name,&(temp[i]));
  1000. }
  1001.  
  1002. /*****************************************************************************
  1003. *
  1004. * FUNCTION
  1005. *
  1006. *   set_output_file_handle
  1007. *
  1008. * INPUT
  1009. *   
  1010. * OUTPUT
  1011. *   
  1012. * RETURNS
  1013. *   
  1014. * AUTHOR
  1015. *
  1016. *   POV-Ray Team
  1017. *   
  1018. * DESCRIPTION
  1019. *
  1020. *   Set the output file handle according to the file type used.
  1021. *
  1022. * CHANGES
  1023. *
  1024. * Oct 95 - Removed test where the output file handle was only set if
  1025. *          output_to_file was TRUE. The output file handle structure
  1026. *          contains a pointer to read line, which is used by the continue
  1027. *          trace option. If you tried a continue trace with file output
  1028. *          manually turned OFF, then a GPF would occur due to a call to a
  1029. *          NULL function pointer.
  1030. *
  1031. ******************************************************************************/
  1032.  
  1033. static void set_output_file_handle()
  1034. {
  1035.   char *def_ext = NULL;
  1036.   char temp[FILE_NAME_LENGTH];
  1037.  
  1038.     switch (opts.OutputFormat)
  1039.     {
  1040.       case '\0':
  1041.       case 's' :
  1042.       case 'S' : Output_File_Handle = GET_SYS_FILE_HANDLE(); def_ext=SYS_DEF_EXT; break;
  1043.  
  1044.       case 't' :
  1045.       case 'T' :
  1046.       case 'c' :
  1047.       case 'C' : Output_File_Handle = Get_Targa_File_Handle(); def_ext=".tga"; break;
  1048.  
  1049.       case 'p' :
  1050.       case 'P' : Output_File_Handle = Get_PPM_File_Handle(); def_ext=".ppm"; break;
  1051.  
  1052.       case 'n' :
  1053.       case 'N' : Output_File_Handle = Get_Png_File_Handle(); def_ext=".png"; break;
  1054.       
  1055.       case 'd' :
  1056.       case 'D' : Error ("Dump format no longer supported.\n"); break;
  1057.       case 'r' :
  1058.       case 'R' : Error ("Raw format no longer supported.\n"); break;
  1059.  
  1060.       default  : Error ("Unrecognized output file format %c.\n",
  1061.                         opts.OutputFormat);
  1062.     }
  1063.  
  1064.     Output_File_Handle->file_type = IMAGE_FTYPE;
  1065.  
  1066.     strcpy(temp,opts.Output_File_Name);
  1067.     
  1068.     POV_SPLIT_PATH(temp,opts.Output_Path,opts.Output_File_Name);
  1069.  
  1070.     if (opts.Output_File_Name[0] == '\0')
  1071.     {
  1072.       sprintf(opts.Output_File_Name, "%s%s",opts.Scene_Name,def_ext);
  1073.     }
  1074.     else
  1075.     {
  1076.        if (!Has_Extension(opts.Output_File_Name))
  1077.        {
  1078.          strcat(opts.Output_File_Name, def_ext);
  1079.        }
  1080.     }
  1081.     
  1082.     strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
  1083. }
  1084.  
  1085. /*****************************************************************************
  1086. *
  1087. * FUNCTION
  1088. *
  1089. *   setup_output_file_name
  1090. *
  1091. * INPUT
  1092. *   
  1093. * OUTPUT
  1094. *
  1095. * RETURNS
  1096. *   
  1097. * AUTHOR
  1098. *
  1099. *   POV-Ray Team
  1100. *   
  1101. * DESCRIPTION
  1102. *
  1103. *   Determine the file name for this frame.  For an animation, the frame
  1104. *   number is inserted into the file name.
  1105. *
  1106. * CHANGES
  1107. *
  1108. *   -
  1109. *
  1110. ******************************************************************************/
  1111.  
  1112. static void setup_output_file_name()
  1113. {
  1114.   char number_string[10];
  1115.   char *plast_period;
  1116.   int available_characters;
  1117.   int ilast_period;
  1118.   int fname_chars;
  1119.  
  1120.   /* This will create the real name for the file */
  1121.   if(opts.FrameSeq.FrameType!=FT_MULTIPLE_FRAME)
  1122.   {
  1123.     strcpy(opts.Output_Numbered_Name,opts.Output_File_Name);
  1124.   }
  1125.   else
  1126.   {
  1127.     /*
  1128.      * This is the maximum number of characters that can be used of the
  1129.      * original filename.  This will ensure that enough space is available
  1130.      * for the frame number in the filename
  1131.      */
  1132.  
  1133.     available_characters = POV_NAME_MAX-opts.FrameSeq.FrameNumWidth;
  1134.  
  1135.     plast_period = strrchr(opts.Output_File_Name, '.');
  1136.  
  1137.     if (plast_period == NULL)
  1138.     {
  1139.       Error("Illegal file name %s -- no extension.\n", opts.Output_File_Name);
  1140.     }
  1141.  
  1142.     ilast_period = plast_period - opts.Output_File_Name;
  1143.  
  1144.     fname_chars = ilast_period;
  1145.  
  1146.     if (fname_chars > available_characters)
  1147.     {
  1148.       /* Only give the warning once */
  1149.  
  1150.       if (opts.FrameSeq.FrameNumber == opts.FrameSeq.InitialFrame)
  1151.       {
  1152.         Warning(0.0, "Need to cut the output filename by %d characters.\n",
  1153.                 ilast_period - available_characters);
  1154.       }
  1155.  
  1156.       fname_chars = available_characters;
  1157.     }
  1158.  
  1159.     /* Perform actual generation of filename */
  1160.  
  1161.     strncpy(opts.Output_Numbered_Name, opts.Output_File_Name, (unsigned)fname_chars);
  1162.  
  1163.     /* strncpy doesn't terminate if strlen(opts.Output_File_Name)<fname_chars */
  1164.  
  1165.     opts.Output_Numbered_Name[fname_chars]='\0';
  1166.  
  1167.     sprintf(number_string, "%0*d", opts.FrameSeq.FrameNumWidth, opts.FrameSeq.FrameNumber);
  1168.  
  1169.     strcat(opts.Output_Numbered_Name, number_string);
  1170.  
  1171.     strcat(opts.Output_Numbered_Name, &opts.Output_File_Name[ilast_period]);
  1172.   }
  1173.  
  1174.   strcpy(Actual_Output_Name,opts.Output_Path);
  1175.   strcat(Actual_Output_Name,opts.Output_Numbered_Name);
  1176. /*
  1177. Debug_Info("P='%s',O='%s',A='%s',N='%s'\n",opts.Output_Path,
  1178.   opts.Output_Numbered_Name, Actual_Output_Name,opts.Output_Numbered_Name);
  1179. */
  1180. }
  1181.  
  1182. /*****************************************************************************
  1183. *
  1184. * FUNCTION
  1185. *
  1186. *   open_output_file
  1187. *
  1188. * INPUT
  1189. *   
  1190. * OUTPUT
  1191. *   
  1192. * RETURNS
  1193. *   
  1194. * AUTHOR
  1195. *
  1196. *   POV-Ray Team
  1197. *   
  1198. * DESCRIPTION
  1199. *
  1200. *   Open file and read in previous image if continued trace is on.
  1201. *
  1202. *   GOTCHA : This saves a POINTER to the file name, so the file
  1203. *            name must exist over the entire life/use of the file
  1204. *
  1205. * CHANGES
  1206. *
  1207. *   -
  1208. *
  1209. ******************************************************************************/
  1210.  
  1211. static void open_output_file()
  1212. {
  1213.   int Buffer_Size;
  1214.   
  1215.   if (opts.Options & DISKWRITE)
  1216.   {
  1217.     Stage = STAGE_FILE_INIT;
  1218.     
  1219.     if (opts.Options & BUFFERED_OUTPUT)
  1220.     {
  1221.        Buffer_Size=opts.File_Buffer_Size;
  1222.     }
  1223.     else
  1224.     {
  1225.        Buffer_Size=0;
  1226.     }
  1227.  
  1228.     if (opts.Options & CONTINUE_TRACE)
  1229.     {
  1230.       Stage = STAGE_CONTINUING;
  1231.  
  1232.       if (Open_File(Output_File_Handle, Actual_Output_Name,
  1233.             &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1234.             READ_MODE) != 1)
  1235.       {
  1236.         Close_File(Output_File_Handle);
  1237.  
  1238.         Warning (0.0,"Error opening continue trace output file.\n");
  1239.  
  1240.         Warning (0.0,"Opening new output file %s.\n",Actual_Output_Name);
  1241.  
  1242.         /* Turn off continue trace */
  1243.  
  1244.         opts.Options &= ~CONTINUE_TRACE;
  1245.  
  1246.         if (Open_File(Output_File_Handle, Actual_Output_Name,
  1247.               &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1248.               WRITE_MODE) != 1)
  1249.         {
  1250.           Error ("Error opening output file.");
  1251.         }
  1252.       }
  1253.     }
  1254.     else
  1255.     {
  1256.       if (Open_File(Output_File_Handle, Actual_Output_Name,
  1257.             &Frame.Screen_Width, &Frame.Screen_Height, Buffer_Size,
  1258.             WRITE_MODE) != 1)
  1259.       {
  1260.         Error ("Error opening output file.");
  1261.       }
  1262.     }
  1263.   }
  1264. }
  1265.  
  1266.  
  1267. /*****************************************************************************
  1268. *
  1269. * FUNCTION
  1270. *
  1271. *   init_vars
  1272. *
  1273. * INPUT
  1274. *   
  1275. * OUTPUT
  1276. *   
  1277. * RETURNS
  1278. *   
  1279. * AUTHOR
  1280. *
  1281. *   POV-Ray Team
  1282. *   
  1283. * DESCRIPTION
  1284. *
  1285. *   Initialize all global variables.
  1286. *
  1287. * CHANGES
  1288. *
  1289. *   -
  1290. *
  1291. ******************************************************************************/
  1292.  
  1293. static void init_vars()
  1294. {
  1295.   ot_fd = NULL;
  1296.   Stage=STAGE_INIT;
  1297.   opts.Abort_Test_Counter = Abort_Test_Every ;
  1298.   Abort_Test_Every = 1;
  1299.   opts.AntialiasDepth = 3;
  1300.   opts.Antialias_Threshold = 0.3;
  1301.   opts.BBox_Threshold = 25;
  1302.   Color_Bits = 8;
  1303.   opts.DisplayFormat = '0';
  1304.   Display_Started = FALSE;
  1305.   opts.File_Buffer_Size = 0;
  1306.   opts.First_Column = 0;
  1307.   opts.First_Column_Percent = 0.0;
  1308.   opts.First_Line = 0;
  1309.   opts.First_Line_Percent = 0.0;
  1310.   Frame.Screen_Height = 100;
  1311.   Frame.Screen_Width  = 100;
  1312.   Root_Object = NULL;
  1313.   free_istack = NULL;
  1314.   opts.JitterScale = 1.0;
  1315.   opts.Language_Version = 3.0;
  1316.   opts.Last_Column = -1;
  1317.   opts.Last_Column_Percent = 1.0;
  1318.   opts.Last_Line = -1;
  1319.   opts.Last_Line_Percent = 1.0;
  1320.   opts.PreviewGridSize_Start = 1;
  1321.   opts.PreviewGridSize_End   = 1;
  1322.   opts.Library_Paths[0] = NULL;
  1323.   opts.Library_Path_Index = 0;
  1324.   Max_Intersections = 64; /*128*/
  1325.   Max_Symbols = Max_Constants = 1024;
  1326.   Number_Of_Files = 0;
  1327.   Number_of_istacks = 0;
  1328.  
  1329.   opts.Options = USE_VISTA_BUFFER + USE_LIGHT_BUFFER + JITTER +
  1330.                  DISKWRITE + REMOVE_BOUNDS;
  1331.   opts.OutputFormat = DEFAULT_OUTPUT_FORMAT;
  1332.   opts.OutputQuality = 8;
  1333.   Output_File_Handle = NULL;
  1334.   opts.Output_Numbered_Name[0]='\0';
  1335.   opts.Output_File_Name[0]='\0';
  1336.   opts.Output_Path[0]='\0';
  1337.   opts.PaletteOption = '3';
  1338.   opts.Quality = 9;
  1339.   opts.Quality_Flags = QUALITY_9;
  1340.   opts.DisplayGamma = DEFAULT_DISPLAY_GAMMA;
  1341.  
  1342.   /* 
  1343.    * If DisplayGamma == 2.2, then GammaFactor == .45, which is what we want.
  1344.    */
  1345.   opts.GammaFactor = DEFAULT_ASSUMED_GAMMA/opts.DisplayGamma;
  1346.  
  1347.   opts.FrameSeq.FrameType = FT_SINGLE_FRAME;
  1348.   opts.FrameSeq.Clock_Value = 0.0;
  1349.   opts.FrameSeq.InitialFrame = 1;
  1350.   opts.FrameSeq.InitialClock = 0.0;
  1351.   opts.FrameSeq.FinalFrame = INT_VALUE_UNSET;
  1352.   opts.FrameSeq.FrameNumWidth = 0;
  1353.   opts.FrameSeq.FinalClock = 1.0;
  1354.   opts.FrameSeq.SubsetStartFrame = INT_VALUE_UNSET;
  1355.   opts.FrameSeq.SubsetStartPercent = DBL_VALUE_UNSET;
  1356.   opts.FrameSeq.SubsetEndFrame = INT_VALUE_UNSET;
  1357.   opts.FrameSeq.SubsetEndPercent = DBL_VALUE_UNSET;
  1358.   opts.FrameSeq.Field_Render_Flag = FALSE;
  1359.   opts.FrameSeq.Odd_Field_Flag = FALSE;
  1360.  
  1361.   opts.Radiosity_Brightness = 3.3;
  1362.   opts.Radiosity_Count = 100;
  1363.   opts.Radiosity_Dist_Max = 0.;   /* default calculated in Radiosity_Initialize */
  1364.   opts.Radiosity_Error_Bound = .4;
  1365.   opts.Radiosity_Gray = .5;       /* degree to which gathered light is grayed */
  1366.   opts.Radiosity_Low_Error_Factor = .8;
  1367.   opts.Radiosity_Min_Reuse = .015;
  1368.   opts.Radiosity_Nearest_Count = 6;
  1369.   opts.Radiosity_Recursion_Limit = 1;
  1370.   opts.Radiosity_Quality = 6;     /* Q-flag value for light gathering */
  1371.   opts.Radiosity_File_ReadOnContinue = 1;
  1372.   opts.Radiosity_File_SaveWhileRendering = 1;
  1373.   opts.Radiosity_File_AlwaysReadAtStart = 0;
  1374.   opts.Radiosity_File_KeepOnAbort = 1;
  1375.   opts.Radiosity_File_KeepAlways = 0;
  1376.  
  1377.  
  1378.   init_statistics(stats);
  1379.   init_statistics(totalstats);
  1380.  
  1381.   strcpy (opts.Input_File_Name, "OBJECT.POV");
  1382.   opts.Scene_Name[0]='\0';
  1383.   opts.Ini_Output_File_Name[0]='\0';
  1384.   opts.Use_Slabs=TRUE;
  1385.   Num_Echo_Lines = 5;   /* May make user setable later - CEY*/
  1386.   Echo_Line_Length = 180;   /* May make user setable later - CEY*/
  1387.  
  1388.   closed_flag = FALSE;
  1389.   Stop_Flag = FALSE;
  1390.  
  1391.   trender = trender_total = 0.0;
  1392.   tparse  = tparse_total  = 0.0;
  1393.  
  1394.   histogram_grid = NULL ;
  1395.   opts.histogram_on = FALSE ;
  1396.   opts.histogram_type = NONE ;
  1397.   opts.Histogram_File_Name[0] = '\0';
  1398.   Histogram_File_Handle = NULL ;
  1399.   /*
  1400.    * Note that late initialization of the histogram_x and histogram_y
  1401.    * variables is done in fix_up_rendering_window, if they aren't specified
  1402.    * on the command line.  This is because they are based on the image
  1403.    * dimensions, and we can't be certain that we have this info at the
  1404.    * time we parse the histogram options in optin.c. [AED]
  1405.    */
  1406.   opts.histogram_x = opts.histogram_y = 0 ;
  1407.   max_histogram_value = 0 ;
  1408.  
  1409.   opts.Tracing_Method = 1;
  1410.   Make_Pigment_Entries();
  1411. }
  1412.  
  1413.  
  1414. /*****************************************************************************
  1415. *
  1416. * FUNCTION
  1417. *
  1418. *   init_statistics
  1419. *
  1420. * INPUT
  1421. *   
  1422. * OUTPUT
  1423. *   
  1424. * RETURNS
  1425. *   
  1426. * AUTHOR
  1427. *
  1428. *   POV-Ray Team
  1429. *   
  1430. * DESCRIPTION
  1431. *
  1432. *   Initialize statistics to 0
  1433. *
  1434. * CHANGES
  1435. *
  1436. *   -
  1437. *
  1438. ******************************************************************************/
  1439.  
  1440. static void init_statistics(pstats)
  1441. COUNTER *pstats;
  1442. {
  1443.   int i;
  1444.  
  1445.   for(i=0; i<MaxStat; i++)
  1446.     Init_Counter(pstats[i]);
  1447. }
  1448.  
  1449. /*****************************************************************************
  1450. *
  1451. * FUNCTION
  1452. *
  1453. *   sum_statistics
  1454. *
  1455. * INPUT
  1456. *   
  1457. * OUTPUT
  1458. *   
  1459. * RETURNS
  1460. *   
  1461. * AUTHOR
  1462. *
  1463. *   POV-Ray Team
  1464. *   
  1465. * DESCRIPTION
  1466. *
  1467. *   Add current statistics to total statistics
  1468. *
  1469. * CHANGES
  1470. *
  1471. *   -
  1472. *
  1473. ******************************************************************************/
  1474.  
  1475. static void sum_statistics(ptotalstats, pstats)
  1476. COUNTER *ptotalstats;
  1477. COUNTER *pstats;
  1478. {
  1479.   int i;
  1480.   COUNTER tmp;
  1481.  
  1482.   for(i=0; i<MaxStat; i++)
  1483.   {
  1484.     Add_Counter(tmp,pstats[i],ptotalstats[i]);
  1485.     ptotalstats[i]=tmp;
  1486.   }
  1487. }
  1488.  
  1489.  
  1490. /*****************************************************************************
  1491. *
  1492. * FUNCTION
  1493. *
  1494. *   variable_store
  1495. *
  1496. * INPUT
  1497. *
  1498. *   flag - flag telling wether to store or restore variables.
  1499. *   
  1500. * OUTPUT
  1501. *   
  1502. * RETURNS
  1503. *   
  1504. * AUTHOR
  1505. *
  1506. *   Dieter Bayer
  1507. *   
  1508. * DESCRIPTION
  1509. *
  1510. *   Store or restore variables whose value has to be the same for all
  1511. *   frames of an animation and who are changed during every frame.
  1512. *
  1513. * CHANGES
  1514. *
  1515. *   May 1995 : Creation.
  1516. *
  1517. ******************************************************************************/
  1518.  
  1519. static void variable_store(Flag)
  1520. int Flag;
  1521. {
  1522.   static int STORE_First_Line;
  1523.  
  1524.   switch (Flag)
  1525.   {
  1526.     case STORE:
  1527.  
  1528.       STORE_First_Line = opts.First_Line;
  1529.  
  1530.       break;
  1531.  
  1532.     case RESTORE:
  1533.  
  1534.       opts.First_Line = STORE_First_Line;
  1535.  
  1536.       break;
  1537.  
  1538.     default:
  1539.  
  1540.       Error("Unknown flag in variable_store().\n");
  1541.   }
  1542. }
  1543.  
  1544. /*****************************************************************************
  1545. *
  1546. * FUNCTION
  1547. *
  1548. *   destroy_libraries
  1549. *
  1550. * INPUT
  1551. *   
  1552. * OUTPUT
  1553. *   
  1554. * RETURNS
  1555. *   
  1556. * AUTHOR
  1557. *
  1558. *   POV-Ray Team
  1559. *   
  1560. * DESCRIPTION
  1561. *
  1562. *   Free library path memory.
  1563. *
  1564. * CHANGES
  1565. *
  1566. *   -
  1567. *
  1568. ******************************************************************************/
  1569.  
  1570. static void destroy_libraries()
  1571. {
  1572.   int i;
  1573.  
  1574.   for (i = 0; i < opts.Library_Path_Index; i++)
  1575.   {
  1576.     POV_FREE(opts.Library_Paths[i]);
  1577.     
  1578.     opts.Library_Paths[i] = NULL;
  1579.   }
  1580. }
  1581.  
  1582.  
  1583.  
  1584. /*****************************************************************************
  1585. *
  1586. * FUNCTION
  1587. *
  1588. *   close_all
  1589. *
  1590. * INPUT
  1591. *   
  1592. * OUTPUT
  1593. *   
  1594. * RETURNS
  1595. *   
  1596. * AUTHOR
  1597. *
  1598. *   POV-Ray Team
  1599. *   
  1600. * DESCRIPTION
  1601. *
  1602. *   Close all the stuff that has been opened and free all allocated memory.
  1603. *
  1604. * CHANGES
  1605. *
  1606. *   -
  1607. *
  1608. ******************************************************************************/
  1609.  
  1610. void close_all()
  1611. {
  1612.   /* Only close things once */
  1613.  
  1614.   if (closed_flag)
  1615.   {
  1616.     return;
  1617.   }
  1618.  
  1619.   if (Output_File_Handle != NULL)
  1620.   {
  1621.     Close_File(Output_File_Handle);
  1622.     
  1623.     POV_FREE(Output_File_Handle);
  1624.     
  1625.     Output_File_Handle = NULL;
  1626.   }
  1627.  
  1628.   destroy_shellouts();
  1629.   destroy_libraries();
  1630.   Destroy_Text_Streams();
  1631.   Free_Noise_Tables();
  1632.   Terminate_Renderer();
  1633.   Destroy_Bounding_Slabs();
  1634.   Destroy_Blob_Queue();
  1635.   Destroy_Vista_Buffer();
  1636.   Destroy_Light_Buffers();
  1637.   Destroy_Random_Generators();
  1638.   Deinitialize_Radiosity_Code();
  1639.  
  1640.   Free_Iteration_Stack();
  1641.   destroy_histogram();
  1642.   Deinitialize_Atmosphere_Code();
  1643.   Deinitialize_BBox_Code();
  1644.   Deinitialize_Lighting_Code();
  1645.   Deinitialize_Mesh_Code();
  1646.   Deinitialize_VLBuffer_Code();
  1647.   Destroy_Frame();
  1648.   Destroy_IStacks();
  1649.   FreeFontInfo();
  1650.  
  1651.   if ((opts.Options & DISPLAY) && Display_Started)
  1652.   {
  1653.     POV_DISPLAY_CLOSE
  1654.   }
  1655.  
  1656.   closed_flag = TRUE;
  1657. }
  1658.  
  1659.  
  1660.  
  1661. /*****************************************************************************
  1662. *
  1663. * FUNCTION
  1664. *
  1665. *   POV_Std_Split_Time
  1666. *
  1667. * INPUT
  1668. *
  1669. * OUTPUT
  1670. *   
  1671. * RETURNS
  1672. *   
  1673. * AUTHOR
  1674. *
  1675. *   POV-Ray Team
  1676. *   
  1677. * DESCRIPTION
  1678. *
  1679. *   Split time into hours, minutes and seconds.
  1680. *
  1681. * CHANGES
  1682. *
  1683. *   -
  1684. *
  1685. ******************************************************************************/
  1686.  
  1687. void POV_Std_Split_Time(time_dif, hrs, mins, secs)
  1688. DBL time_dif;
  1689. unsigned long *hrs, *mins;
  1690. DBL *secs;
  1691. {
  1692.   *hrs = (unsigned long)(time_dif / 3600.0);
  1693.  
  1694.   *mins = (unsigned long)((time_dif - (DBL)(*hrs * 3600)) / 60.0);
  1695.  
  1696.   *secs = time_dif - (DBL)(*hrs * 3600 + *mins * 60);
  1697. }
  1698.  
  1699.  
  1700.  
  1701.  
  1702. /*****************************************************************************
  1703. *
  1704. * FUNCTION
  1705. *
  1706. *   pov_stricmp
  1707. *
  1708. * INPUT
  1709. *   
  1710. * OUTPUT
  1711. *   
  1712. * RETURNS
  1713. *   
  1714. * AUTHOR
  1715. *
  1716. *   POV-Ray Team
  1717. *   
  1718. * DESCRIPTION
  1719. *
  1720. *   Since the stricmp function isn't available on all systems, we've
  1721. *   provided a simplified version of it here.
  1722. *
  1723. * CHANGES
  1724. *
  1725. *   -
  1726. *
  1727. ******************************************************************************/
  1728.  
  1729. int pov_stricmp (s1, s2)
  1730. char *s1, *s2;
  1731. {
  1732.   char c1, c2;
  1733.  
  1734.   while ((*s1 != '\0') && (*s2 != '\0'))
  1735.   {
  1736.     c1 = *s1++;
  1737.     c2 = *s2++;
  1738.  
  1739.     if (islower(c1))
  1740.     {
  1741.       c1 = (char)toupper(c1);
  1742.     }
  1743.  
  1744.     if (islower(c2))
  1745.     {
  1746.       c2 = (char)toupper(c2);
  1747.     }
  1748.  
  1749.     if (c1 < c2)
  1750.     {
  1751.       return(-1);
  1752.     }
  1753.  
  1754.     if (c1 > c2)
  1755.     {
  1756.       return(1);
  1757.     }
  1758.   }
  1759.  
  1760.   if (*s1 == '\0')
  1761.   {
  1762.     if (*s2 == '\0')
  1763.     {
  1764.       return(0);
  1765.     }
  1766.     else
  1767.     {
  1768.       return(-1);
  1769.     }
  1770.   }
  1771.   else
  1772.   {
  1773.     return(1);
  1774.   }
  1775. }
  1776.  
  1777.  
  1778. /*****************************************************************************
  1779. *
  1780. * FUNCTION
  1781. *
  1782. *   Locate_File
  1783. *
  1784. * INPUT
  1785. *   
  1786. * OUTPUT
  1787. *   
  1788. * RETURNS
  1789. *   
  1790. * AUTHOR
  1791. *
  1792. *   POV-Ray Team
  1793. *   
  1794. * DESCRIPTION
  1795. *
  1796. *   Find a file in the search path.
  1797. *
  1798. * CHANGES
  1799. *
  1800. *   Apr 1996: Don't add trailing FILENAME_SEPARATOR if we are immediately
  1801. *             following DRIVE_SEPARATOR because of Amiga probs.  [AED]
  1802. *
  1803. ******************************************************************************/
  1804.  
  1805. FILE *Locate_File (filename, mode, ext1, ext2, err_flag)
  1806. char *filename, *mode, *ext1, *ext2; int err_flag;
  1807. {
  1808.   int i,l1,l2;
  1809.   char pathname[FILE_NAME_LENGTH];
  1810.   char file0[FILE_NAME_LENGTH];
  1811.   char file1[FILE_NAME_LENGTH];
  1812.   char file2[FILE_NAME_LENGTH];
  1813.   FILE *f;
  1814.  
  1815.   if (Has_Extension(filename))
  1816.   {
  1817.      l1=l2=0;
  1818.   }
  1819.   else
  1820.   {
  1821.      if ((l1 = strlen(ext1)) > 0)
  1822.      {
  1823.         strcpy(file1, filename);
  1824.         strcat(file1, ext1);
  1825.      }
  1826.  
  1827.      if ((l2 = strlen(ext2)) > 0)
  1828.      {
  1829.         strcpy(file2, filename);
  1830.         strcat(file2, ext2);
  1831.      }
  1832.   }
  1833.  
  1834.   /* Check the current directory first. */
  1835.   if (l1)
  1836.   {
  1837.      if ((f = fopen(file1, mode)) != NULL)
  1838.      {
  1839.        return(f);
  1840.      }
  1841.   }
  1842.   if (l2)
  1843.   {
  1844.      if ((f = fopen(file2, mode)) != NULL)
  1845.      {
  1846.        return(f);
  1847.      }
  1848.   }
  1849.   if ((f = fopen(filename, mode)) != NULL)
  1850.   {
  1851.      return(f);
  1852.   }
  1853.  
  1854.   for (i = 0; i < opts.Library_Path_Index; i++)
  1855.   {
  1856.     strcpy(file0, opts.Library_Paths[i]);
  1857.     file0[strlen(file0)+1] = '\0';
  1858.     if (file0[strlen(file0) - 1] != DRIVE_SEPARATOR)
  1859.       file0[strlen(file0)] = FILENAME_SEPARATOR;
  1860.  
  1861.     if (l1)
  1862.     {
  1863.        strcpy(pathname, file0);
  1864.        strcat(pathname, file1);
  1865.        if ((f = fopen(pathname, mode)) != NULL)
  1866.        {
  1867.           return(f);
  1868.        }
  1869.     }
  1870.  
  1871.     if (l2)
  1872.     {
  1873.        strcpy(pathname, file0);
  1874.        strcat(pathname, file2);
  1875.        if ((f = fopen(pathname, mode)) != NULL)
  1876.        {
  1877.           return(f);
  1878.        }
  1879.     }
  1880.     strcpy(pathname, file0);
  1881.     strcat(pathname, filename);
  1882.     if ((f = fopen(pathname, mode)) != NULL)
  1883.     {
  1884.       return(f);
  1885.     }
  1886.   }
  1887.  
  1888.   if (err_flag)
  1889.   {
  1890.     if (l1)
  1891.     {
  1892.       Error_Line("Could not find file '%s%s'\n",filename,ext1);
  1893.     }
  1894.     else
  1895.     {
  1896.       Error_Line("Could not find file '%s'\n",filename);
  1897.     }
  1898.   }
  1899.   
  1900.   return(NULL);
  1901. }
  1902.  
  1903. /*****************************************************************************
  1904. *
  1905. * FUNCTION
  1906. *
  1907. * INPUT
  1908. *   
  1909. * OUTPUT
  1910. *   
  1911. * RETURNS
  1912. *   
  1913. * AUTHOR
  1914. *   
  1915. * DESCRIPTION
  1916. *
  1917. * CHANGES
  1918. *
  1919. ******************************************************************************/
  1920.  
  1921. static int Has_Extension (name)
  1922. char *name;
  1923. {
  1924.    char *p;
  1925.  
  1926.    if (name!=NULL)
  1927.    {
  1928.      p=strrchr(name, '.');
  1929.  
  1930.      if (p!=NULL)
  1931.      {
  1932.         if ((strlen(name)-(p-name))<=4)
  1933.         {
  1934.            return (TRUE);
  1935.         }
  1936.      }
  1937.    }
  1938.    return (FALSE);
  1939. }
  1940.  
  1941.  
  1942. /*****************************************************************************
  1943. *
  1944. * FUNCTION
  1945. *
  1946. *   pov_shellout
  1947. *
  1948. * INPUT
  1949. *
  1950. *   template_command - the template command string to execute
  1951. *   
  1952. * OUTPUT
  1953. *
  1954. * RETURNS
  1955. *
  1956. * AUTHOR
  1957. *
  1958. *   POV-Ray Team
  1959. *
  1960. * DESCRIPTION
  1961. *
  1962. *   Execute the command line described by the string being passed in
  1963. *
  1964. * CHANGES
  1965. *
  1966. *   -
  1967. *
  1968. ******************************************************************************/
  1969.  
  1970. SHELLRET pov_shellout (Type)
  1971. SHELLTYPE Type;
  1972. {
  1973.   char real_command[POV_MAX_CMD_LENGTH];
  1974.   int i, j, l = 0;
  1975.   int length;
  1976.   SHELLRET Return_Code;
  1977.   char *s = NULL;
  1978.   char *template_command;
  1979.  
  1980.  
  1981.   if ( opts.Shellouts == NULL ) return(IGNORE_RET);
  1982.  
  1983.   template_command=opts.Shellouts[Type].Command;
  1984.  
  1985.   if ((length = strlen(template_command)) == 0)
  1986.   {
  1987.     return(IGNORE_RET);
  1988.   }
  1989.  
  1990.   switch(Type)
  1991.   {
  1992.     case PRE_SCENE_SHL:  s="pre-scene";   break;
  1993.     case PRE_FRAME_SHL:  s="pre-frame";   break;
  1994.     case POST_FRAME_SHL: s="post-frame";  break;
  1995.     case POST_SCENE_SHL: s="post-scene";  break;
  1996.     case USER_ABORT_SHL: s="user about";  break;
  1997.     case FATAL_SHL:      s="fatal error"; break;
  1998.     case MAX_SHL: /* To remove warnings*/ break;
  1999.   }
  2000.  
  2001.   Status_Info("\nPerforming %s shell-out command",s);
  2002.  
  2003.   /* First, find the real command */
  2004.  
  2005.   for (i = 0, j = 0; i < length; )
  2006.   {
  2007.     if (template_command[i] == '%')
  2008.     {
  2009.       switch (toupper(template_command[i+1]))
  2010.       {
  2011.          case 'O':
  2012.  
  2013.           strncpy(&real_command[j], opts.Output_Numbered_Name, 
  2014.                (unsigned)(l=strlen(opts.Output_Numbered_Name)));
  2015.  
  2016.           break;
  2017.  
  2018.          case 'P':
  2019.  
  2020.           strncpy(&real_command[j], opts.Output_Path,(unsigned)(l=strlen(opts.Output_Path)));
  2021.  
  2022.           break;
  2023.  
  2024.          case 'S':
  2025.  
  2026.           strncpy(&real_command[j], opts.Scene_Name, (unsigned)(l=strlen(opts.Scene_Name)));
  2027.  
  2028.           break;
  2029.  
  2030.          case 'N':
  2031.  
  2032.           sprintf(&real_command[j],"%d",opts.FrameSeq.FrameNumber);
  2033.           l = strlen(&real_command[j]);
  2034.  
  2035.           break;
  2036.  
  2037.          case 'K':
  2038.  
  2039.           sprintf(&real_command[j],"%f",opts.FrameSeq.Clock_Value);
  2040.           l = strlen(&real_command[j]);
  2041.  
  2042.           break;
  2043.  
  2044.          case 'H':
  2045.  
  2046.           sprintf(&real_command[j],"%d",Frame.Screen_Height);
  2047.           l = strlen(&real_command[j]);
  2048.  
  2049.           break;
  2050.  
  2051.          case 'W':
  2052.  
  2053.           sprintf(&real_command[j],"%d",Frame.Screen_Width);
  2054.           l = strlen(&real_command[j]);
  2055.  
  2056.           break;
  2057.  
  2058.          case '%':
  2059.  
  2060.           real_command[j]='%';
  2061.  
  2062.           l=1;
  2063.  
  2064.           break;
  2065.        }
  2066.  
  2067.        j+=l;
  2068.  
  2069.        i+=2; /* we used 2 characters of template_command */
  2070.     }
  2071.     else
  2072.     {
  2073.       real_command[j++]=template_command[i++];
  2074.     }
  2075.   }
  2076.  
  2077.   real_command[j]='\0';
  2078.  
  2079.   Return_Code=POV_SYSTEM(real_command);
  2080.  
  2081.   if (opts.Shellouts[Type].Inverse)
  2082.   {
  2083.     Return_Code=!Return_Code;
  2084.   }
  2085.  
  2086.   if (Return_Code)
  2087.   {
  2088.     if (Type < USER_ABORT_SHL)
  2089.     {
  2090.       switch(opts.Shellouts[Type].Ret)
  2091.       {
  2092.         case FATAL_RET:
  2093.  
  2094.           Error("Fatal error returned from shellout command.");
  2095.  
  2096.           break;
  2097.  
  2098.         case USER_RET:
  2099.  
  2100.           Check_User_Abort(TRUE); /* the TRUE forces user abort */
  2101.  
  2102.           break;
  2103.  
  2104.         case QUIT_RET:
  2105.  
  2106.           Terminate_POV(0);
  2107.  
  2108.           break;
  2109.  
  2110.         case IGNORE_RET:
  2111.         case SKIP_ONCE_RET:
  2112.         case ALL_SKIP_RET: /* Added to remove warnings */
  2113.           break;
  2114.       }
  2115.     }
  2116.  
  2117.     return(opts.Shellouts[Type].Ret);
  2118.   }
  2119.  
  2120.   return(IGNORE_RET);
  2121. }
  2122.  
  2123. /*****************************************************************************
  2124. *
  2125. * FUNCTION
  2126. *
  2127. * INPUT
  2128. *   
  2129. * OUTPUT
  2130. *   
  2131. * RETURNS
  2132. *
  2133. * AUTHOR
  2134. *
  2135. * DESCRIPTION
  2136. *
  2137. * CHANGES
  2138. *
  2139. ******************************************************************************/
  2140.  
  2141. static void init_shellouts()
  2142. {
  2143.   int i;
  2144.  
  2145.   opts.Shellouts=POV_MALLOC(sizeof(SHELLDATA)*MAX_SHL,"shellout data");
  2146.  
  2147.   for (i=0; i < MAX_SHL; i++)
  2148.   {
  2149.     opts.Shellouts[i].Ret=IGNORE_RET;
  2150.     opts.Shellouts[i].Inverse=FALSE;
  2151.     opts.Shellouts[i].Command[0]='\0';
  2152.   }
  2153. }
  2154.  
  2155. /*****************************************************************************
  2156. *
  2157. * FUNCTION
  2158. *
  2159. * INPUT
  2160. *
  2161. * OUTPUT
  2162. *
  2163. * RETURNS
  2164. *
  2165. * AUTHOR
  2166. *
  2167. * DESCRIPTION
  2168. *
  2169. * CHANGES
  2170. *
  2171. ******************************************************************************/
  2172.  
  2173. static void destroy_shellouts()
  2174. {
  2175.   if (opts.Shellouts != NULL)
  2176.   {
  2177.     POV_FREE(opts.Shellouts);
  2178.   }
  2179.  
  2180.   opts.Shellouts=NULL;
  2181. }
  2182.  
  2183.  
  2184. /*****************************************************************************
  2185. *
  2186. * FUNCTION
  2187. *
  2188. *   closest_power_of_2
  2189. *
  2190. * INPUT
  2191. *
  2192. *   theNumber - the value to determine closest power of 2 for.
  2193. *
  2194. * OUTPUT
  2195. *
  2196. * RETURNS
  2197. *
  2198. *   The closest power of two is returned, or zero if the
  2199. *   argument is less than or equal to zero.
  2200. *
  2201. * AUTHOR
  2202. *
  2203. *   Eduard Schwan
  2204. *
  2205. * DESCRIPTION
  2206. *
  2207. *   Decription: Find the highest positive power of 2 that is
  2208. *   less than or equal to the number passed.
  2209. *
  2210. *   Input  Output
  2211. *   -----  ------
  2212. *     0      0
  2213. *     1      1
  2214. *     2      2
  2215. *     3      2
  2216. *     8      8
  2217. *     9      8
  2218. *
  2219. * CHANGES
  2220. *
  2221. *   Aug 1994 : Created by Eduard.
  2222. *
  2223. ******************************************************************************/
  2224.  
  2225. static unsigned closest_power_of_2(theNumber)
  2226. unsigned theNumber;
  2227. {
  2228.   int PowerOf2Counter;
  2229.  
  2230.   /* do not handle zero or negative numbers for now */
  2231.  
  2232.   if (theNumber <= 0)
  2233.   {
  2234.     return(0);
  2235.   }
  2236.  
  2237.   /* count the number in question down as we count up a power of 2 */
  2238.  
  2239.   PowerOf2Counter = 1;
  2240.  
  2241.   while (theNumber > 1)
  2242.   {
  2243.     /* move our power of 2 counter bit up... */
  2244.  
  2245.     PowerOf2Counter <<= 1;
  2246.  
  2247.     /* and reduce our test number by a factor of 2 two */
  2248.  
  2249.     theNumber >>= 1;
  2250.   }
  2251.  
  2252.   return(PowerOf2Counter);
  2253. }
  2254.  
  2255. /*****************************************************************************
  2256. *
  2257. * FUNCTION
  2258. *
  2259. *   pre_init_povray
  2260. *
  2261. * INPUT -- none
  2262. *
  2263. * OUTPUT
  2264. *
  2265. * RETURNS
  2266. *
  2267. * AUTHOR -- CEY
  2268. *
  2269. * DESCRIPTION
  2270. *
  2271. *   This routine does essential initialization that is required before any
  2272. *   POV_MALLOC-like routines may be called and before any text streams
  2273. *   may be used.
  2274. *   
  2275. *   If you are using alt_main and need access to any part of the generic code
  2276. *   before alt_main is called, you MUST call this routine first!  Also note
  2277. *   that it is safe to call it twice.  If you don't call it, alt_main will.
  2278. *   It won't hurt if you both do it.
  2279. *   
  2280. *   NOTE: Terminate_POV de-initializes these features.  Therefore you may
  2281. *   need to call it again between sucessive calls to alt_main.  If you call
  2282. *   pre_init_povray but for some reason you abort and don't call alt_main,
  2283. *   then you should call Terminate_POV to clean up.
  2284. *
  2285. * CHANGES
  2286. *   Nov 1995 : Created by CEY
  2287. *
  2288. ******************************************************************************/
  2289.  
  2290. void pre_init_povray()
  2291. {
  2292.   if (pre_init_flag==1234)
  2293.   {
  2294.     return;
  2295.   }
  2296.       
  2297.   /* Initialize memory. */
  2298.   mem_init();
  2299.  
  2300.   /* Initialize streams. In USERIO.C */
  2301.   Init_Text_Streams();
  2302.  
  2303.   init_shellouts();
  2304.  
  2305.   pre_init_tokenizer ();
  2306.   
  2307.   pre_init_flag=1234;
  2308. }
  2309.  
  2310. void POV_Split_Path(s,p,f)
  2311. char *s;
  2312. char *p;
  2313. char *f;
  2314. {
  2315. char *l;
  2316.  
  2317.   strcpy(p,s);
  2318.  
  2319.   if ((l=strrchr(p,FILENAME_SEPARATOR))==NULL)
  2320.   {
  2321.      if ((l=strrchr(p,DRIVE_SEPARATOR))==NULL)
  2322.      {
  2323.         strcpy(f,s);
  2324.         p[0]='\0';
  2325.         return;
  2326.      }
  2327.   }
  2328.   
  2329.   l++;
  2330.   strcpy(f,l);
  2331.   *l='\0';
  2332.  
  2333. }
  2334.